
#include <BCube>
#include <BCone>
#include <BSphere>
#include <BCylinder>
#include <BCapsule>
#include <BStyle>
#include <BTreeWidget>
#include <BGraphicWidget>
#include <BApplication>

#include "Utilities.h"

BString FindValidName(const BScene* scene, const BString& name)
{
	int stop = name.size();
	while (stop-- >= 0)
	{
		if (!name.isDigit(stop))
		{
			stop++;
			break;
		}
	}
	BString realName;
	int number = 0;
	while (number < 9999)
	{
		realName.reset();
		realName.append(name, 0, stop);
		realName.append(number++);
		if (scene->contain(realName))
			continue;
		break;
	}
	return realName;
}
BString FindValidName(const BGroup* group, const BString& name)
{
	int stop = name.size();
	while (stop-- >= 0)
	{
		if (!name.isDigit(stop))
		{
			stop++;
			break;
		}
	}
	BString realName;
	int number = 0;
	while (number < 9999)
	{
		realName.reset();
		realName.append(name, 0, stop);
		realName.append(number++);
		if (group->contain(realName))
			continue;
		break;
	}
	return realName;
}
BString FindValidName(const BNode* node, const BString& name)
{
	int stop = name.size();
	while (stop-- >= 0)
	{
		if (!name.isDigit(stop))
		{
			stop++;
			break;
		}
	}
	BString realName;
	int number = 0;
	while (number < 9999)
	{
		realName.reset();
		realName.append(name, 0, stop);
		realName << number++;
		if (node->shape(realName))
			continue;
		break;
	}
	return realName;
}

BString FindValidName(const BTreeWidget* treeWidget, const BString& name)
{
	int stop = name.size();
	while (stop-- >= 0)
	{
		if (!name.isDigit(stop))
		{
			stop++;
			break;
		}
	}
	BString realName;
	int number = 0;
	while (number < 9999)
	{
		realName.reset();
		realName.append(name, 0, stop);
		realName << number++;
		if (treeWidget->item(realName))
			continue;
		break;
	}
	return realName;
}
BString FindValidName(const BTreeItem* item, const BString& name)
{
	int stop = name.size();
	while (stop-- >= 0)
	{
		if (!name.isDigit(stop))
		{
			stop++;
			break;
		}
	}
	BString realName;
	int number = 0;
	while (number < 9999)
	{
		realName.reset();
		realName.append(name, 0, stop);
		realName << number++;
		if (item->child(realName))
			continue;
		break;
	}
	return realName;
}
BString FindValidName(const BGraphicWidget* graphicWidget, const BString& name)
{
	int stop = name.size();
	while (stop-- >= 0)
	{
		if (!name.isDigit(stop))
		{
			stop++;
			break;
		}
	}
	BString realName;
	int number = 0;
	while (number < 9999)
	{
		realName.reset();
		realName.append(name, 0, stop);
		realName << number++;
		if (graphicWidget->item(realName))
			continue;
		break;
	}
	return realName;
}
BString FindValidName(const BGraphicItem* item, const BString& name)
{
	int stop = name.size();
	while (stop-- >= 0)
	{
		if (!name.isDigit(stop))
		{
			stop++;
			break;
		}
	}
	BString realName;
	int number = 0;
	while (number < 9999)
	{
		realName.reset();
		realName.append(name, 0, stop);
		realName << number++;
		if (item->child(realName))
			continue;
		break;
	}
	return realName;
}

bool SmoothImage(BImage* image, float factor)
{
	int fmtlen = image->fmtlen();
	BByteArray* pixels = image->pixels();
	if (fmtlen > 0 && pixels && pixels->size())
	{
		BByteArray bytes = *pixels;
		BByte* ptrs[9];
		float fact = 1.0f / sqrt(2.0f);
		float mult = 1.0f / (fact * 4.0f + 4.0f + factor);
		int width = image->width();
		int height = image->height();
		for (int row = 0; row < height; row++)
		{
			int prev = fmtlen * width * (row - 1);
			BByte* prevData = bytes.data() + prev;
			int curr = fmtlen * width * row;
			BByte* currData = bytes.data() + curr;
			int next = fmtlen * width * (row + 1);
			BByte* nextData = bytes.data() + next;
			for (int col = 0; col < width; col++)
			{
				int offset = fmtlen * col;
				BByte* ptr = pixels->data() + curr + offset;
				if (row > 0)
				{
					ptrs[0] = prevData + offset - fmtlen;
					ptrs[1] = prevData + offset;
					ptrs[2] = prevData + offset + fmtlen;
				}
				else
				{
					ptrs[0] = 0;
					ptrs[1] = 0;
					ptrs[2] = 0;
				}
				if (col > 0)
					ptrs[3] = currData + offset - fmtlen;
				else
					ptrs[3] = 0;
				ptrs[4] = currData + offset;
				if (col < width - 1)
					ptrs[5] = currData + offset + fmtlen;
				else
					ptrs[5] = 0;
				if (row < height - 1)
				{
					ptrs[6] = nextData + offset - fmtlen;
					ptrs[7] = nextData + offset;
					ptrs[8] = nextData + offset + fmtlen;
				}
				else
				{
					ptrs[6] = 0;
					ptrs[7] = 0;
					ptrs[8] = 0;
				}
				for (int i = 0; i < fmtlen; i++)
				{
					float v = 0;
					if (ptrs[0]) { v += *ptrs[0] * fact;	ptrs[0]++; }
					if (ptrs[1]) { v += *ptrs[1];			ptrs[1]++; }
					if (ptrs[2]) { v += *ptrs[2] * fact;	ptrs[2]++; }
					if (ptrs[3]) { v += *ptrs[3];			ptrs[3]++; }
					if (ptrs[4]) { v += *ptrs[4] * factor;	ptrs[4]++; }
					if (ptrs[5]) { v += *ptrs[5];		  	ptrs[5]++; }
					if (ptrs[6]) { v += *ptrs[6] * fact;  	ptrs[6]++; }
					if (ptrs[7]) { v += *ptrs[7];		  	ptrs[7]++; }
					if (ptrs[8]) { v += *ptrs[8] * fact;  	ptrs[8]++; }
					*ptr = (BByte)(v * mult);
					ptr++;
				}
			}
		}
		return true;
	}
	return false;
}

BIcon* TypedIcon(BObject* object, const BStyle* style)
{
	if (!object)
		return 0;
	for (int i = object->typeCount() - 1; i >= 0; i--)
	{
		const char* type = object->typeName(i);
		if (BIcon* icon = style->icon(type))
		{
			return icon;
		}
	}
	return 0;
}
BImage* TypedImage(BObject* object, const BStyle* style)
{
	if (!object)
		return 0;
	for (int i = object->typeCount() - 1; i >= 0; i--)
	{
		const char* type = object->typeName(i);
		if (BIcon* icon = style->icon(type))
		{
			return icon->image();
		}
	}
	return 0;
}

BIcon* TypedIcon(BObject* object)
{
	if (!object)
		return 0;
	const BStyle* style = BApplication::style();
	for (int i = object->typeCount() - 1; i >= 0; i--)
	{
		const BString& type = object->typeName(i);
		if (BIcon* icon = style->icon(type))
		{
			return icon;
		}
	}
	return 0;
}
BImage* TypedImage(BObject* object)
{
	if (!object)
		return 0;
	const BStyle* style = BApplication::style();
	for (int i = object->typeCount() - 1; i >= 0; i--)
	{
		const char* type = object->typeName(i);
		if (BIcon* icon = style->icon(type))
		{
			return icon->image();
		}
	}
	return 0;
}

BIcon* TypedIcon(BObject* object, const BWidget* widget)
{
	if (!object)
		return 0;
	while (widget)
	{
		if (BStyle* style = widget->style())
		{
			if (BIcon* icon = TypedIcon(object, style))
				return icon;
		}
		widget = widget->parent();
	}
	BStyle* style = BApplication::style();
	if (BIcon* icon = TypedIcon(object, style))
		return icon;
	return 0;
}
BImage* TypedImage(BObject* object, const BWidget* widget)
{
	if (!object)
		return 0;
	while (widget)
	{
		if (BStyle* style = widget->style())
		{
			if (BImage* image = TypedImage(object, style))
				return image;
		}
		widget = widget->parent();
	}
	BStyle* style = BApplication::style();
	if (BImage* image = TypedImage(object, style))
		return image;
	return 0;
}

BShape* CreateProxy(BShape* shape, const BString& type)
{
	BShape* proxy = 0;
	const BBox& box = shape->box();
	if (type == "Cube")
	{
		proxy = new BCube(box.lena() * 2, box.lenb() * 2, box.lenc() * 2);
	}
	else if (type == "Cone")
	{
		proxy = new BCone(box.radius(), box.lenc());
	}
	else if (type == "Sphere")
	{
		proxy = new BSphere(box.radius());
	}
	else if (type == "Cylinder")
	{
		proxy = new BCylinder(box.radius(), box.lenc());
	}
	else if (type == "Capsule")
	{
		proxy = new BCapsule(box.radius(), box.lenc());
	}
	shape->setProperty("proxy", proxy);
	shape->fresh();
	if (proxy)
	{
		proxy->setMatrix(shape->matrix());
		proxy->setTransparent(true);
	}
	return proxy;
}
